#include <p18cxxx.h>
#include <stdio.h>
#include <adc.h>
#include <delays.h>
#include <usart.h>
#include <string.h>	
#include <pwm.h>
#include <timers.h>
//Filtru de ordinul 6, deci calculul va avea 7 termeni
#define N 7
//5 coef si 2 de y
#define M 5
#define Z 2

/***************************************************
MENIU
***************************************************/
unsigned char meniu_FIR_IIR()
{ unsigned char op=0x01; //Initial == optiunea 1 (FIR)
  PORTD=op<<2;
  while (1)
{
 	if (PORTDbits.RD0==0)  // verificam butonul RD0 e apasat 
        {
          Delay10KTCYx(5);// asteptam un pic si mai verificam odata pt a stabili
          if (PORTDbits.RD0==0)// daca intr-adevar a fost o apasare de buton
		          if (op<3) op++;
                     else op=1; 
             PORTD=op<<2;//punem pe port n deplasat la stanga cu 2 
         Delay10KTCYx(500);    
        }
	if (PORTDbits.RD1==0)  // verificam butonul RD1 e apasat 
        {
          Delay10KTCYx(5);
          if (PORTDbits.RD1==0)
                Delay10KTCYx(500); 
          		break;//Iesim din meniu
        }
}
  return op; //Return 1 sau 2 (FIR sau IIR) sau 3 (nefiltrat)
}

unsigned char meniu_Filter()
{ /*1- lowpass
    2- highpass
    3- passband*/
unsigned char op=0x01;
  PORTD=op<<2;
  while (1)
{
    if (PORTDbits.RD0==0)  // verificam butonul RD0 e apasat 
        {
          Delay10KTCYx(5);// asteptam un pic si mai verificam odata pt a stabili
          if (PORTDbits.RD0==0)// daca intr-adevar a fost o apasare de buton
		          if (op<3) op++;
                     else op=0x01; 
             PORTD=op<<2;//punem pe port n deplasat la stanga cu 2 
         Delay10KTCYx(500);    
        }
    if (PORTDbits.RD1==0)  // verificam butonul RD1 e apasat 
        {
          Delay10KTCYx(5);
          if (PORTDbits.RD1==0)
                Delay10KTCYx(500); 
          	    break;//Iesim din meniu
        }
}
return op;
}
unsigned char op_FIR_IIR;
unsigned char op_Filter;
/**********************************************************************/

extern void asm_fir();
extern void asm_iir();
extern void asm_direct();

//H -> coeficientii activi
unsigned char* H = 0;
//y..
unsigned long y = 0;
//x[n]..
unsigned char x[N] = {0,0,0,0,0,0,0};
//y[n]
unsigned char y_last[Z] = {0, 0};
//X pentru scazut
unsigned long X = 0;
//coef FIR
unsigned char hhp[N] = {144,   112,    81,   191,    81,   112,   144};
unsigned char hlp[N] = {133,   154,   182,   196,   182,   154,   133};
unsigned char hpb[N] = {124,    75,   125,   255,   125,    75,   124};
//coef IIR
unsigned char ilp[M] = {191,   254,  191,    29,   168};
unsigned char ihp[M] = {165,    53,   165,   128,   149};


void main (void)
{

// Disable analog components
ADCON1 = 0x0F;
CMCON  = 0x07;
TRISD = 0x03;
PORTD = 0;
	
// setup timer prescaler - 1:1 needed by the PWM module
T2CONbits.T2CKPS1 = 0;
T2CONbits.T2CKPS0 = 0;

// start timer 2
T2CONbits.TMR2ON = 1;

TRISAbits.TRISA0 = 1;

// configure PORTD
TRISDbits.TRISD0 = 1;
TRISDbits.TRISD1 = 1;
TRISDbits.TRISD2 = 0;
TRISDbits.TRISD3 = 0;

PORTDbits.RD2 = 1;
PORTDbits.RD3 = 1;

OpenUSART(  USART_TX_INT_OFF  &
            USART_RX_INT_OFF  &
            USART_ASYNCH_MODE &
            USART_EIGHT_BIT   &
            USART_CONT_RX     &
            USART_BRGH_HIGH,
            64);

 stdout = _H_USART;

//op = meniu();
//printf("\n\r Optiunea:%d", op);

//CloseUSART();

OpenADC( ADC_FOSC_16 &
         ADC_RIGHT_JUST &
         ADC_4_TAD,
		 ADC_CH0 &
         ADC_INT_OFF &
         ADC_REF_VDD_VSS,
         ADC_1ANA);

OpenPWM1( 156 /*19*/ );//8kHz 38

SetDCPWM1(0);
//X = 0
X = 0;
//coef activi
H = ilp;

op_FIR_IIR = 0xFF;
/*******************************************************/
printf("\n\r");//******************************
op_FIR_IIR = meniu_FIR_IIR();
//Afisare optiune pe serial
printf("\n\r Optiunea FIR IIR:%d", op_FIR_IIR);

op_Filter = 0xFF;
if (op_FIR_IIR!=3)
{
op_Filter = meniu_Filter();//*******************************
//Afisare optiune pe serial
printf("\n\r Filtrul:%d", op_Filter);
/********************************************************/
}


if (op_FIR_IIR==1)
{
switch (op_Filter)
	{
		case 0x01:  H = hlp; break;
		case 0x02:  H = hhp; break;
		case 0x03:  H = hpb; break;
  	  	  default: break;
	}
}
if (op_FIR_IIR==2)
{
switch (op_Filter)
	{
		case 0x01:  H = ilp; break;
		case 0x02:  H = ihp; break;
		case 0x03:  //H = ipb; 
                    break;
  	  	  default: break;
	}
}
printf("\n\r FIR IIR:%d", op_FIR_IIR);
printf("\n\r Filtrul:%d", op_Filter);
 // Setup and start timer
OpenTimer0( T0_8BIT & TIMER_INT_ON & T0_SOURCE_INT & T0_PS_1_2 );
TMR0L=0x80;
// Enable interrupts
INTCONbits.GIE = 1;

while (1);

}

void InterruptHandlerHigh();

#pragma code _HIGH_INTERRUPT_VECTOR = 0x808
void _high_ISR(void)
{
	_asm
	    goto InterruptHandlerHigh
	_endasm
}


#pragma code
#pragma interrupt InterruptHandlerHigh

void InterruptHandlerHigh()
{
	if(INTCONbits.TMR0IF)
	{	TMR0L=0x80;

        if (op_FIR_IIR==1)
        asm_fir();
            else 
             if (op_FIR_IIR==2)
                 asm_iir();
          else 
              asm_direct();

		INTCONbits.TMR0IF = 0;
	}
				
}
